import { SubscribeMessage, WebSocketGateway, WebSocketServer, OnGatewayDisconnect } from '@nestjs/websockets';

@WebSocketGateway({ cors: true })
export class SyncOperationGateway implements OnGatewayDisconnect {

  @WebSocketServer()
  private server
  private masterId = null
  private players = []
  private frameNumber = 0;
  private frameNumberOperationMap = new Map()
  private frameNumberForUpdate = 0
  private generateFrameNumberInterval = null

  private clear() {
    clearInterval(this.generateFrameNumberInterval)
    this.frameNumber = 0
    this.masterId = null
    this.frameNumberOperationMap = new Map()
  }

  @SubscribeMessage('startGame')
  startGame() {
    this.clear()
    this.server.emit('toMainScene', this.players)
  }

  @SubscribeMessage('finishLoad')
  finishLoad(client: any) {
    const { id } = client
    this.players.forEach(player => {
      if (player.id === id) {
        player.finishLoad = true
      }
    })
    let allFinishLoad = true
    this.players.forEach(player => {
      if (player.finishLoad === false) allFinishLoad = false
    })
    if (allFinishLoad === true) {
      this.generateFrameNumberInterval = setInterval(() => {
        this.server.emit('receiveFrameNumber', this.frameNumber)
        const frameNumber = this.frameNumber
        setTimeout(() => {
          this.server.emit('receiveOperation', frameNumber, this.frameNumberOperationMap.get(frameNumber) ?? {})
          this.frameNumberForUpdate = frameNumber
        }, 100)
        this.frameNumber++
      }, 1000 / 50)
    }
  }

  @SubscribeMessage('finishReady')
  finishReady(client) {
    const { id } = client
    this.players.forEach(player => {
      if (player.id === id) {
        player.isReady = true
      }
    })
    this.server.emit('updatePlayers', this.players)
  }

  handleDisconnect(client: any) {
    const { id } = client
    this.players = this.players.filter(player => player.id !== id)
    if (this.masterId === id && this.players.length > 0) {
      this.masterId = this.players[0].id
      this.players[0].isMaster = true
    }
    if (this.players.length === 0) this.clear()
    this.server.emit('updatePlayers', this.players)
  }

  @SubscribeMessage('registerPlayer')
  registerPlayer(client: any, [nickName, ballColor, x, y]) {
    const { id } = client
    let isMaster = false
    if (this.masterId === null) {
      this.masterId = id
      isMaster = true
    }
    this.players.push({ id, nickName, ballColor, x, y, isReady: false, isMaster, finishLoad: false })
    console.log(this.players)
    this.server.emit('updatePlayers', this.players)
  }

  @SubscribeMessage('sendChatText')
  sendChatText(client: any, chatText: string) {
    this.server.emit('receiveChatText', { chatText, sendId: client.id, sendTime: new Date().getTime() })
  }

  //监听 w,a,d 四个按键，down为按下，up为没按下
  @SubscribeMessage('sendOperation')
  sendOperation(client: any, { frameNumber, w, a, d }: { frameNumber: number, w: 'up' | 'down', a: 'up' | 'down', d: 'up' | 'down' }) {
    const { id } = client
    if (this.frameNumberOperationMap.has(frameNumber)) {
      const playerOprationMap = this.frameNumberOperationMap.get(frameNumber)
      playerOprationMap[id] = { w, a, d }
    } else {
      const playerOprationMap = {}
      playerOprationMap[id] = { w, a, d }
      this.frameNumberOperationMap.set(frameNumber, playerOprationMap)
    }
  }

  @SubscribeMessage('requestBatchFrameOperation')
  requestBatchFrameOperation(client: any, frameNumberForUpdate: number) {
    console.log('requestBatchFrameOperation',this.frameNumberForUpdate,frameNumberForUpdate)
    if (this.frameNumberForUpdate > frameNumberForUpdate) {
      const frameOperations = []
      const length = Math.min(this.frameNumberForUpdate - frameNumberForUpdate, 100)
      console.log('length', length)
      for (let i = 0; i < length; i++) {
        frameOperations.push(this.frameNumberOperationMap.get(frameNumberForUpdate + i))
      }
      return {
        event: "receiveBatchFrameOperation",
        data: {
          frameNumberForUpdate,
          frameOperations
        }
      }
    }
  }
}
